﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Threading;

namespace DataMonitoringOrPlayBack
{
    public class GetSource
    {
        private UdpClient _udp = null;
        private IPEndPoint _ipe = null;
        private FileStream _fsSrc = null;
        private FileStream _fsWav = null;
        private string curFileName = string.Empty;
        private string curWaveName = string.Empty;
        private DateTime _startTime = DateTime.Now;
        
        private long lsrcIndex = 0;
        private long lwavIndex = 0;

        public GetSource(int iRecPort)
        {
            try
            {
                _udp = new UdpClient(iRecPort);
                _ipe = new IPEndPoint(IPAddress.Any, iRecPort);
            }
            catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.StackTrace + ":" + ex.Message); }
        }
        public void ReceiveData()
        {
            Queue<byte[]> CurSecSorce = new Queue<byte[]>(2 * 1024 * 1024);
            Queue<double[]> CurSecWav = new Queue<double[]>(2 * 1024 * 1024);
            
            DateTime dt = DateTime.Now.AddMilliseconds(100);
            DateTime dlog = DateTime.Now.AddSeconds(1);

            while (true)
            {
                try
                {
                    byte[] bytes = _udp.Receive(ref _ipe);
                    if (bytes.Length % 512 != 0) continue;
                    CurSecSorce.Enqueue(bytes);
                    lsrcIndex += 512;

                    double[] _tmpData = new double[256];
                    for (int n = 0; n < 256; n++)
                    {
                        _tmpData[n] = double.Parse(BitConverter.ToUInt16(bytes, 2 * n).ToString());
                    }
                    double dAvrg = _tmpData.Average() +5000;
                    for (int i = 0; i < _tmpData.Length; i++)
                    {
                        if (_tmpData[i] <= dAvrg)
                        {
                            _tmpData[i] = 0;
                        }
                    }
                    double[] _wavlen = new double[30];
                    CSource.GetWavesLength(_tmpData, ref _wavlen);
                    CurSecWav.Enqueue(_wavlen);
                    lwavIndex += _wavlen.Length * 8;

                    if (dt <= DateTime.Now)
                    {
                        dt = DateTime.Now.AddMilliseconds(100);
                        byte[][] _bb = CurSecSorce.ToArray();
                        CurSecSorce.Clear();
                        ////保存原始数据
                        //ThreadPool.QueueUserWorkItem(new WaitCallback(SaveBuffer), _bb);
                        double[][] _dd = CurSecWav.ToArray();
                        CurSecWav.Clear();
                        ////计算显示波长信息
                        //ThreadPool.QueueUserWorkItem(new WaitCallback(SaveWavLen), _dd);

                        //保存数据
                        Dictionary<byte[][], double[][]> dataobj = new Dictionary<byte[][], double[][]>(32*1024*1024);
                        dataobj.Add(_bb,_dd);
                        ThreadPool.QueueUserWorkItem(new WaitCallback(SaveData),dataobj);

                        //显示光谱波长信息
                        Dictionary<byte[], double[][]> tmpobj = new Dictionary<byte[], double[][]>(32 * 1024 * 1024);
                        tmpobj.Add((byte[])bytes.Clone(),_dd);
                        ThreadPool.QueueUserWorkItem(new WaitCallback(WriteBytesToDouble), tmpobj);

                    }
                    if (dlog <= DateTime.Now)
                    {
                        dlog = DateTime.Now.AddSeconds(1);
                        CSource.mutqlong.WaitOne();
                        CSource._lIndexDir.Add(lsrcIndex,lwavIndex);
                        CSource.mutqlong.ReleaseMutex();
                        System.Diagnostics.Debug.WriteLine(CSource.lCount.ToString());
                    }
                }
                catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.StackTrace + ":" + ex.Message); }
            }
        }
        /// <summary>
        /// 写原始光谱波长到缓冲区
        /// </summary>
        /// <param name="o"></param>
        private void WriteBytesToDouble(object o)
        {
            try
            {
                Dictionary<byte[],double[][]> tmpobj=o as Dictionary<byte[],double[][]>;
                Queue<double[]> _dwav=new Queue<double[]> (1024*1024);
                foreach (KeyValuePair<byte[], double[][]> kvp in tmpobj)
                {
                    byte[] _tmp = (byte[])kvp.Key.Clone();
                    if (_tmp.Length % 512 != 0)
                    {
                        continue;
                    }
                    double[] _tmpData = new double[256];
                    for (int n = 0; n < 256; n++)
                    {
                        _tmpData[n] = double.Parse(BitConverter.ToUInt16(_tmp, 2 * n).ToString());
                    }
                    CSource.dSpectrum = _tmpData;
                    foreach (double[] d in kvp.Value)
                    {
                        _dwav.Enqueue(d);
                    }
                }
                CSource.mutqwavsrc.WaitOne();
                if (CSource._queWavSource.Count > 15)
                {
                    CSource._queWavSource.Dequeue();
                }
                CSource._queWavSource.Enqueue(_dwav);
                CSource.mutqwavsrc.ReleaseMutex();

            }
            catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.StackTrace + ":" + ex.Message); }
        }


        private void SaveData(object o)
        {
            try
            {
                Dictionary<byte[][], double[][]> tmpobj = o as Dictionary<byte[][], double[][]>;
                Queue<byte[][]> tmpbyte = new Queue<byte[][]>(32 * 1024 * 1024);
                Queue<double[][]> tmpdouble = new Queue<double[][]>(32 * 1024 * 1024);
                foreach (KeyValuePair<byte[][], double[][]> kvp in tmpobj)
                {
                    tmpbyte.Enqueue(kvp.Key);
                    tmpdouble.Enqueue(kvp.Value);
                }
                if (curFileName == string.Empty)
                {
                    _startTime = DateTime.Now;
                    curFileName = string.Format("{0}.dat", _startTime.ToString("yyyyMMddHHmmss"));
                    curWaveName=string.Format("{0}.lav", _startTime.ToString("yyyyMMddHHmmss"));
                }
                if (_startTime.AddHours(1) <= DateTime.Now)
                {
                    _startTime = DateTime.Now;
                    curFileName = string.Format("{0}.dat", _startTime.ToString("yyyyMMddHHmmss"));
                    curWaveName=string.Format("{0}.lav", _startTime.ToString("yyyyMMddHHmmss"));
                }
                CSource.mutsavesource.WaitOne();
                if (!File.Exists(CSource.strDirPath + "\\" + curFileName))
                {
                    if (_fsSrc != null)
                    {
                        string strInx = _fsSrc.Name;
                        _fsSrc.Close();
                        _fsSrc.Dispose();
                        _fsSrc = null;
                        CSource.mutqlong.WaitOne();
                        int len = CSource._lIndexDir.Count;
                        if (len > 0)
                        {
                            long[] lSrcArray = CSource._lIndexDir.Keys.ToArray();
                            long[] lWavArray = CSource._lIndexDir.Values.ToArray();
                            CSource._lIndexDir.Clear();
                            lsrcIndex = lwavIndex = 0;
                            CSource.mutqlong.ReleaseMutex();
                            FileStream _ffss = File.OpenWrite(strInx.Replace(".dat", ".inx"));
                            for (int i = 0; i < len; i++)
                            {
                                _ffss.Write(BitConverter.GetBytes(lSrcArray[i]), 0, 8);
                                _ffss.Write(BitConverter.GetBytes(lWavArray[i]), 0, 8);
                            }
                            _ffss.Close();
                        }
                        else
                        {
                            CSource.mutqlong.ReleaseMutex();
                        }
                    }
                    _fsSrc = File.OpenWrite(CSource.strDirPath + "\\" + curFileName);
                }
                //保存波长数据
                if (!File.Exists(CSource.strDirPath + "\\" + curWaveName))
                {
                    if (_fsWav != null)
                    {
                        _fsWav.Close();
                        _fsWav.Dispose();
                        _fsWav = null;
                    }
                    _fsWav = File.OpenWrite(CSource.strDirPath + "\\" + curWaveName);
                }
                if (_fsWav == null)
                {
                    _fsWav = File.OpenWrite(CSource.strDirPath + "\\" + curWaveName);
                }
                foreach (double[][] dd in tmpdouble)
                {
                    foreach (double[] d in dd)
                    {
                        foreach(double _d in d)
                        {
                            _fsWav.Write(BitConverter.GetBytes(_d), 0, 8);
                        }
                    }
                }
                //保存光谱数据
                if (_fsSrc == null)
                {
                    _fsSrc = File.OpenWrite(CSource.strDirPath + "\\" + curFileName);
                    CSource.strCurPath = _fsSrc.Name;
                }
                
                foreach (byte[][] bb in tmpbyte)
                {
                    foreach (byte[] b in bb)
                    {
                        _fsSrc.Write(b, 0, b.Length);
                    }
                }
                CSource.mutsavesource.ReleaseMutex();
            }
            catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.StackTrace + ":" + ex.Message); }
        }
        /// <summary>
        /// 保存原始光谱到文件
        /// </summary>
        /// <param name="o"></param>
        //private void SaveBuffer(object o)
        //{
        //    try
        //    {
        //        byte[][] _bb = o as byte[][];
        //        byte[][] _Atmp = (byte[][])_bb.Clone();
        //        if (curFileName == string.Empty)
        //        {
        //            _startTime = DateTime.Now;
        //            curFileName = string.Format("{0}.dat", _startTime.ToString("yyyyMMddHHmmss"));
        //        }
        //        if (_startTime.AddHours(1) <= DateTime.Now)
        //        {
        //            _startTime = DateTime.Now;
        //            curFileName = string.Format("{0}.dat", _startTime.ToString("yyyyMMddHHmmss"));
        //        }
        //        CSource.mutsavesource.WaitOne();
        //        if (!File.Exists(CSource.strDirPath + "\\" + curFileName))
        //        {
        //            if (_fs != null)
        //            {
        //                string strInx = _fs.Name;
        //                _fs.Close();
        //                _fs.Dispose();
        //                _fs = null;
        //                CSource.mutqlong.WaitOne();
        //                int len = CSource._Quelong.Count;
        //                if (len > 0)
        //                {
        //                    long[] lArray = CSource._Quelong.ToArray();
        //                    CSource._Quelong.Clear();
        //                    lCount = 0;
        //                    CSource.mutqlong.ReleaseMutex();
        //                    FileStream _ffss = File.OpenWrite(strInx.Replace(".dat", ".inx"));
        //                    foreach (long l in lArray)
        //                    {
        //                        _ffss.Write(BitConverter.GetBytes(l), 0, 8);
        //                    }
        //                    _ffss.Close();
        //                }
        //                else
        //                {
        //                    CSource.mutqlong.ReleaseMutex();
        //                }
        //            }
        //            _fs = File.OpenWrite(CSource.strDirPath + "\\" + curFileName);
        //        }
        //        if (_fs == null)
        //        {
        //            _fs = File.OpenWrite(CSource.strDirPath + "\\" + curFileName);
        //            CSource.strCurPath = _fs.Name;
        //        }
        //        foreach (byte[] b in _Atmp)
        //        {
        //            _fs.Write(b, 0, b.Length);
        //        }
        //        CSource.mutsavesource.ReleaseMutex();
        //    }
        //    catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.StackTrace + ":" + ex.Message); }
        //}
        /// <summary>
        /// 写时时波长到缓冲区
        /// </summary>
        ///// <param name="o"></param>
        //private void SaveWavLen(object o)
        //{
        //    try
        //    {
        //        byte[][] _bb = o as byte[][];
        //        byte[][] _Atmp = (byte[][])_bb.Clone();
        //        Queue<double[]> _wav = new Queue<double[]>(10 * 8 * 1024);

        //        foreach (byte[] b in _Atmp)
        //        {
        //            if (b.Length != 512) continue;
        //            double[] _tmpData = new double[256];
        //            for (int n = 0; n < 256; n++)
        //            {
        //                _tmpData[n] = double.Parse(BitConverter.ToUInt16(b, 2 * n).ToString());
        //            }
        //            double dAvrg = _tmpData.Average() + 400;
        //            for (int i = 0; i < _tmpData.Length; i++)
        //            {
        //                if (_tmpData[i] <= dAvrg)
        //                {
        //                    _tmpData[i] = 0;
        //                }
        //            }
        //            double[] _wavlen = new double[30];
        //            CSource.GetWavesLength(_tmpData, ref _wavlen);
        //            _wav.Enqueue(_wavlen);
        //        }
        //        CSource.mutqwavsrc.WaitOne();
        //        if (CSource._queWavSource.Count > 15)
        //        {
        //            CSource._queWavSource.Dequeue();
        //        }
        //        CSource._queWavSource.Enqueue(_wav);
        //        CSource.mutqwavsrc.ReleaseMutex();
        //    }
        //    catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.StackTrace + ":" + ex.Message); }
        //}
    }
}

